#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <flgrCoreData.h>
#include <flgrCoreDispatch.h>
#include <flgrCoreVector.h>
#include <flgrCoreArithVector.h>
#include <flgrCoreCopy.h>
#include <flgrCoreIO.h>
#include <flgrCoreDataIO.h>
#include <flgrCoreNhbManage.h>

#include "macro.h"

const char *getStringErrorCode(FLGR_Ret ret) {
  switch(ret) {
  case   0 : return "FLGR_RET_OK";
  case  -1 : return "FLGR_RET_TYPE_UNKNOWN";
  case  -2 : return "FLGR_RET_TYPE_DIFFERENT";
  case  -3 : return "FLGR_RET_SIZE_ERROR";
  case  -4 : return "FLGR_RET_ALLOCATION_ERROR";
  case  -5 : return "FLGR_RET_CONNEXITY_UNKNOWN";
  case  -6 : return "FLGR_RET_PARAM_UNKNOWN";
  case  -7 : return "FLGR_RET_NOT_IMPLEMENTED";
  case  -8 : return "FLGR_RET_UNDEFINED_ERROR";
  case  -9 : return "FLGR_RET_NULL_OBJECT";
  case -10 : return "FLGR_RET_VECTOR_SIZE_DIFFERENT";
  case -11 : return "FLGR_RET_VECTOR_SIZE_ERROR";
  case -12 : return "FLGR_RET_PARAM_ERROR";
  default:
    return "*** UNKNOWN ERROR CODE ***";
  }
}



/////////////////////////////////////////////////////////////////////////
// Test Macro for displaying images results
/////////////////////////////////////////////////////////////////////////
#define macro_display_vector(dtype,motif,cast)		\
  dtype val;						\
  dtype *pval = (dtype*) vec->array;			\
							\
  printf("[");						\
  for(j=0;j<vec->spp-1;j++) {				\
    val = flgr_get_array_##dtype(pval,j);		\
    printf(motif ",",(cast)(val));			\
  }							\
  j=vec->spp-1;						\
  val =  flgr_get_array_##dtype(pval,j);		\
  printf(motif "]",(cast) (val))



void display_vector(FLGR_Vector *vec) {
  int j;

  if(vec->type==FLGR_UINT8) {
    macro_display_vector(fgUINT8,"%Ld",long long);

  }else if(vec->type==FLGR_UINT16) {
    macro_display_vector(fgUINT16,"%Ld",long long);

  }else if(vec->type==FLGR_UINT32) {
    macro_display_vector(fgUINT32,"%Ld",long long);

  }else if(vec->type==FLGR_UINT64) {
    macro_display_vector(fgUINT64,"%Ld",long long);

  }else if(vec->type==FLGR_INT8) {
    macro_display_vector(fgINT8,"%Ld",long long);

  }else if(vec->type==FLGR_INT16) {
    macro_display_vector(fgINT16,"%Ld",long long);

  }else if(vec->type==FLGR_INT32) {
    macro_display_vector(fgINT32,"%Ld",long long);

  }else if(vec->type==FLGR_INT64) {
    macro_display_vector(fgINT64,"%Ld",long long);

  }else if(vec->type==FLGR_FLOAT32) {
    macro_display_vector(fgFLOAT32,"%03.3f",double);

  }else if(vec->type==FLGR_FLOAT64) {
    macro_display_vector(fgFLOAT64,"%03.3f",double);

  }else if(vec->type==FLGR_BIT) {
    macro_display_vector(fgBIT,"%Ld",long long);

  }else {
    fprintf(stderr,"unknown vector type\n");
  }

}



void display_vector_false(FLGR_Vector *vec) {
  printf("\033[1;31m");
  display_vector(vec);
  printf("\033[0m");
}




/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// VECTOR CHECK
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////



void print_vector(FLGR_Vector *vec) {
  display_vector(vec);
  printf("\n");
}

void print_vector_false(FLGR_Vector *vec) {
  display_vector_false(vec);
  printf("\n");
}


/////////////////////////////////////////////////////////////////////////
// Test Macro for checking results
/////////////////////////////////////////////////////////////////////////
#define macro_check_vector(dtype)				\
  dtype v1,v2;							\
  dtype *pval1 = (dtype*) vec1->array;				\
  dtype *pval2 = (dtype*) vec2->array;				\
								\
  for(j=0;j<vec1->spp;j++) {					\
    v1 = flgr_get_array_##dtype(pval1,j);			\
    v2 = flgr_get_array_##dtype(pval2,j);			\
    if( ((long long) v1) != ((long long)v2)) {			\
      fprintf(stderr,"Error in Vector position %d\n",j);	\
      return -1;						\
    }								\
  }								\
								\
  return 0

int check_vector(FLGR_Vector *vec1, FLGR_Vector *vec2) {
  int j;

  if(vec1->type==FLGR_UINT8) {
    macro_check_vector(fgUINT8);

  }else if(vec1->type==FLGR_UINT16) {
    macro_check_vector(fgUINT16);

  }else if(vec1->type==FLGR_UINT32) {
    macro_check_vector(fgUINT32);

  }else if(vec1->type==FLGR_UINT64) {
    macro_check_vector(fgUINT64);

  }else if(vec1->type==FLGR_INT8) {
    macro_check_vector(fgINT8);

  }else if(vec1->type==FLGR_INT16) {
    macro_check_vector(fgINT16);

  }else if(vec1->type==FLGR_INT32) {
    macro_check_vector(fgINT32);

  }else if(vec1->type==FLGR_INT64) {
    macro_check_vector(fgINT64);

  }else if(vec1->type==FLGR_FLOAT32) {
    macro_check_vector(fgFLOAT32);

  }else if(vec1->type==FLGR_FLOAT64) {
    macro_check_vector(fgFLOAT64);

  }else if(vec1->type==FLGR_BIT) {
    macro_check_vector(fgBIT);
  }else {
    fprintf(stderr,"unknown vector type\n");
    return -1;
  }

}


int _check_and_display_vector(FLGR_Vector *vecref,  FLGR_Vector *vec, FLGR_Ret ret, const char *calling_fct) {
  printf("%s",calling_fct);
  if(ret==FLGR_RET_NOT_IMPLEMENTED) {
    printf(": NOT IMPLEMENTED\n");
    return 0;
  }
  if(ret!=FLGR_RET_OK) {
    printf(": failed (ret = %s)!\n",getStringErrorCode(ret));
    return -1;
  }
  if(check_vector(vec,vecref)==-1) {
    printf("Vector Reference:\n");
    print_vector(vecref);\
    printf("Vector Obtained:\n");
    print_vector_false(vec);
    return -1;

  }else printf(": ok\n");

  return 0;
}











/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// DATA1D CHECK
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////



/////////////////////////////////////////////////////////////////////////
// Test Macro for printing images results
/////////////////////////////////////////////////////////////////////////
void print_data1d(FLGR_Data1D *dat) {
  FLGR_Vector *vec=flgr_vector_create(dat->spp,dat->type);
  int j;

  for(j=0 ; j<dat->length ; j++) {
    flgr1d_get_data_vector(dat,j,vec);
    display_vector(vec);

    if(j!=dat->length-1)
      printf(", ");
    
    if( (j%10 == 9) || (j==dat->length-1)) printf("\n");

  }
  printf("\n\n");
  
  flgr_vector_destroy(vec);
}

void print_data1d_false(FLGR_Data1D *datref, FLGR_Data1D *dat) {
  FLGR_Vector *vec=flgr_vector_create(dat->spp,dat->type);
  FLGR_Vector *vecref=flgr_vector_create(datref->spp,dat->type);
  int j;

  for(j=0 ; j<dat->length ; j++) {
    flgr1d_get_data_vector(dat,j,vec);
    flgr1d_get_data_vector(datref,j,vecref);

    if(flgr_vector_equal(vec,vecref)==FLGR_TRUE) {
      display_vector(vec);
    }else {
      display_vector_false(vec);
    }
    
    if(j!=dat->length-1)
      printf(", ");

    if( (j%10 == 9) || (j==dat->length-1)) printf("\n");

  }
  printf("\n\n");
  flgr_vector_destroy(vec);
  flgr_vector_destroy(vecref);  
}


int check_data1d(FLGR_Data1D *datref, FLGR_Data1D *dat) {
  FLGR_Vector *vec;
  FLGR_Vector *vecref;
  int j;

  if(datref->spp != dat->spp) {
    fprintf(stderr, "Spp different ref=%d dat=%d\n",datref->spp,dat->spp);
    return -1;
  }

  vec = flgr_vector_create(dat->spp,dat->type);
  vecref = flgr_vector_create(datref->spp,dat->type);

  for(j=0 ; j<dat->length ; j++) {
    flgr1d_get_data_vector(dat,j,vec);
    flgr1d_get_data_vector(datref,j,vecref);

    if((vec->type == FLGR_FLOAT32) || (vec->type == FLGR_FLOAT64)) {
      flgr_vector_floor(vecref,vecref);
      flgr_vector_floor(vec,vec);
    }
    
    if(flgr_vector_equal(vec,vecref)==FLGR_FALSE) {
      fprintf(stderr,"Error in Data1D Position %d\n",j);
      return -1;
    }

  }

  flgr_vector_destroy(vec);
  flgr_vector_destroy(vecref);  
  return 0;
}


int _check_and_display_data1d(FLGR_Data1D *datref, FLGR_Data1D *dat, FLGR_Ret ret,const char *calling_fct) {
  printf("%s",calling_fct);
  if(ret==FLGR_RET_NOT_IMPLEMENTED) {
    printf(": NOT IMPLEMENTED\n");
    return 0;
  }							
  if(ret!=FLGR_RET_OK) {				
    printf(": failed (ret = %s)!\n",getStringErrorCode(ret));		
    return -1;						
  }							
  if(check_data1d(datref,dat)==-1) {	
    printf(": failed!\n");				
    printf("Signal Reference:\n");			
    print_data1d(datref);				
    printf("Signal Obtained:\n");			
    print_data1d_false(datref,dat);			
    return -1;						
    
  }else printf(": ok\n");
  
  return 0;
}












/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// DATA2D CHECK
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////





void print_data2d(FLGR_Data2D *dat) {
  FLGR_Vector *vec=flgr_vector_create(dat->spp,dat->type);
  int i,j;

  for(i=0 ; i<dat->size_y ; i++) {
    for(j=0 ; j<dat->size_x ; j++) {
      flgr2d_get_data_vector(dat,i,j,vec);
      display_vector(vec);

      if(j==dat->size_x-1)
	printf("\n");
      else
	printf(", ");
    }
  }
  printf("\n\n");
  
  flgr_vector_destroy(vec);
}

void print_data2d_false(FLGR_Data2D *datref,FLGR_Data2D *dat) {
  FLGR_Vector *vec=flgr_vector_create(dat->spp,dat->type);
  FLGR_Vector *vecref=flgr_vector_create(datref->spp,dat->type);
  int i,j;

  for(i=0 ; i<dat->size_y ; i++) {
    for(j=0 ; j<dat->size_x ; j++) {
      flgr2d_get_data_vector(dat,i,j,vec);
      flgr2d_get_data_vector(datref,i,j,vecref);

      if(flgr_vector_equal(vec,vecref)==FLGR_TRUE) {
	display_vector(vec);
      }else {
	display_vector_false(vec);
      }
    
      if(j==dat->size_x-1)
	printf("\n");
      else
	printf(", ");
    }
  }
  printf("\n\n");
  flgr_vector_destroy(vec);
  flgr_vector_destroy(vecref);  
}


int check_data2d(FLGR_Data2D *datref,FLGR_Data2D *dat) {
  FLGR_Vector *vec=flgr_vector_create(dat->spp,dat->type);
  FLGR_Vector *vecref=flgr_vector_create(datref->spp,dat->type);
  int i,j;

  for(i=0 ; i<dat->size_y ; i++) {
    for(j=0 ; j<dat->size_x ; j++) {
      flgr2d_get_data_vector(dat,i,j,vec);
      flgr2d_get_data_vector(datref,i,j,vecref);

      if((vec->type == FLGR_FLOAT32) || (vec->type == FLGR_FLOAT64)) {
	flgr_vector_floor(vecref,vecref);
	flgr_vector_floor(vec,vec);
      }

      if(flgr_vector_equal(vec,vecref)!=FLGR_TRUE) {
	fprintf(stderr,"Error in Data2D Position row: %d - col: %d\n",i,j);
	check_vector(vec,vecref);
	return -1;
      }
    }
  }
  flgr_vector_destroy(vec);
  flgr_vector_destroy(vecref);  
  return 0;
}


int _check_and_display_data2d(FLGR_Data2D *imgref, FLGR_Data2D *img, FLGR_Ret ret,const char *calling_fct) {
  printf("%s",calling_fct);
  if(ret==FLGR_RET_NOT_IMPLEMENTED) {
    printf(": NOT IMPLEMENTED\n");
    return 0;
  }							
  if(ret!=FLGR_RET_OK) {				
    printf(": failed (ret = %s)!\n",getStringErrorCode(ret));		
    return -1;						
  }							
  if(check_data2d(imgref,img)==-1) {			
    printf(": failed!\n");				
    printf("Image Reference:\n");			
    print_data2d(imgref);				
    printf("Image Obtained:\n");			
    print_data2d_false(imgref,img);			
    return -1;						
    
  }else printf(": ok\n");
  
  return 0;
}









/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// NHB BOX1D CHECK
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////


#define FLGR_MACRO_PRINT_NEIGHBOR_BOX1D(dtype,motif)			\
  dtype *list_data_val;							\
  dtype *list_nhb_val;							\
  int *list_coord_x;							\
  int *size = (int *) extr->size;					\
  int i,k;								\
									\
  printf("--------------------------------------\n");			\
									\
  printf("Center coord  x : %d",extr->center_coord_x);			\
  printf("\nCenter Data val : ");					\
  display_vector(extr->center_data_val);				\
  printf("\nCenter Nhb val : ");					\
  display_vector(extr->center_nhb_val);					\
									\
  for(k=0 ; k<extr->spp ; k++) {					\
    list_data_val = (dtype *) extr->list_data_val[k];			\
    list_nhb_val = (dtype *) extr->list_nhb_val[k];			\
    list_coord_x =(int*) extr->list_coord_x[k];				\
    printf("\n\nChannel %d\n",k);					\
									\
    printf("\nCoord : ");						\
    for(i=0 ; i<size[k] ; i++) printf("%3d ",list_coord_x[i]);		\
									\
    printf("\nData  : ");						\
    for(i=0 ; i<size[k] ; i++) printf(motif " ",list_data_val[i]);	\
									\
    printf("\nNhb   : ");						\
    for(i=0 ; i<size[k] ; i++) printf(motif " ",list_nhb_val[i]);	\
									\
    printf("\n--------------------------------------\n");		\
  }									\
       

void print_neighbor_box1d_fgBIT(FLGR_NhbBox1D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX1D(fgBIT,"%3Ld");
}
void print_neighbor_box1d_fgUINT8(FLGR_NhbBox1D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX1D(fgUINT8,"%3d");
}
void print_neighbor_box1d_fgUINT16(FLGR_NhbBox1D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX1D(fgUINT16,"%3d");
}
void print_neighbor_box1d_fgUINT32(FLGR_NhbBox1D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX1D(fgUINT32,"%3d");
}
void print_neighbor_box1d_fgINT8(FLGR_NhbBox1D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX1D(fgINT8,"%3d");
}
void print_neighbor_box1d_fgINT16(FLGR_NhbBox1D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX1D(fgINT16,"%3d");
}
void print_neighbor_box1d_fgINT32(FLGR_NhbBox1D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX1D(fgINT32,"%3d");
}
void print_neighbor_box1d_fgFLOAT32(FLGR_NhbBox1D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX1D(fgFLOAT32,"%.2f");
}
void print_neighbor_box1d_fgFLOAT64(FLGR_NhbBox1D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX1D(fgFLOAT64,"%.2f");
}

void print_neighbor_box1d(FLGR_NhbBox1D *extr) {
  switch(extr->type) {
  case FLGR_BIT:      print_neighbor_box1d_fgBIT(extr);break;
  case FLGR_UINT8:    print_neighbor_box1d_fgUINT8(extr);break;
  case FLGR_UINT16:   print_neighbor_box1d_fgUINT16(extr);break;
  case FLGR_UINT32:   print_neighbor_box1d_fgUINT32(extr);break;
  case FLGR_INT8:     print_neighbor_box1d_fgINT8(extr);break;
  case FLGR_INT16:    print_neighbor_box1d_fgINT16(extr);break;
  case FLGR_INT32:    print_neighbor_box1d_fgINT32(extr);break;
  case FLGR_FLOAT32:  print_neighbor_box1d_fgFLOAT32(extr);break;
  case FLGR_FLOAT64:  print_neighbor_box1d_fgFLOAT64(extr);break;
  default:
    fprintf(stderr,"%s:type error\n",__FUNCTION__);    
  }
}





#define FLGR_MACRO_CHECK_NEIGHBOR_BOX1D(dtype)				\
  dtype *list_data_val1;						\
  dtype *list_nhb_val1;							\
  int *list_coord_x1;							\
  int *size1 = (int*) extr1->size;					\
  dtype *list_data_val2;						\
  dtype *list_nhb_val2;							\
  int *list_coord_x2;							\
  int *size2 = (int*) extr2->size;					\
  int i,k;								\
									\
  if(extr1->spp != extr2->spp) {					\
    fprintf(stderr,"Sample per pixel error\n");				\
    return -1;								\
  }									\
									\
  if(extr1->nhb_size_x != extr2->nhb_size_x) {				\
    fprintf(stderr,"nhb size x error\n");				\
    return -1;								\
  }									\
									\
  for(k=0 ; k<extr1->spp ; k++) {					\
    if(size1[k] != size2[k]) {						\
      fprintf(stderr,"neighbor box1d size error\n");			\
      return -1;							\
    }									\
  }									\
									\
  if(extr1->center_coord_x != extr2->center_coord_x) {			\
    fprintf(stderr,"center coord error\n");				\
    return -1;								\
  }									\
									\
  									\
  if(flgr_vector_equal(extr1->center_data_val, extr2->center_data_val)	\
     != FLGR_TRUE) {							\
    fprintf(stderr,"center data error\n");				\
    return -1;								\
  }									\
									\
  if(flgr_vector_equal(extr1->center_nhb_val, extr2->center_nhb_val)	\
     != FLGR_TRUE) {							\
    fprintf(stderr,"center nhb error\n");				\
    return -1;								\
  }									\
									\
  for(k=0 ; k<extr1->spp ; k++) {					\
									\
    list_data_val1 = (dtype *) extr1->list_data_val[k];			\
    list_nhb_val1 = (dtype *) extr1->list_nhb_val[k];			\
    list_coord_x1 =(int*) extr1->list_coord_x[k];			\
    list_data_val2 = (dtype *) extr2->list_data_val[k];			\
    list_nhb_val2 = (dtype *) extr2->list_nhb_val[k];			\
    list_coord_x2 =(int*) extr2->list_coord_x[k];			\
									\
    for(i=0 ; i<size1[k] ; i++) {					\
      if(list_coord_x1[i] != list_coord_x2[i]) {			\
	fprintf(stderr,"extracted list coord error\n");			\
	return -1;							\
      }									\
      if(list_nhb_val1[i] != list_nhb_val2[i]) {			\
	fprintf(stderr,"extracted list nhb error\n");			\
	return -1;							\
      }									\
      if(list_data_val1[i] != list_data_val2[i]) {			\
	fprintf(stderr,"extracted list data error\n");			\
	return -1;							\
      }									\
    }									\
  }									\
									\
  return 0

int check_neighbor_box1d_fgBIT(FLGR_NhbBox1D *extr1, FLGR_NhbBox1D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX1D(fgBIT);
}
int check_neighbor_box1d_fgUINT8(FLGR_NhbBox1D *extr1, FLGR_NhbBox1D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX1D(fgUINT8);
}
int check_neighbor_box1d_fgUINT16(FLGR_NhbBox1D *extr1, FLGR_NhbBox1D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX1D(fgUINT16);
}
int check_neighbor_box1d_fgUINT32(FLGR_NhbBox1D *extr1, FLGR_NhbBox1D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX1D(fgUINT32);
}
int check_neighbor_box1d_fgINT8(FLGR_NhbBox1D *extr1, FLGR_NhbBox1D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX1D(fgINT8);
}
int check_neighbor_box1d_fgINT16(FLGR_NhbBox1D *extr1, FLGR_NhbBox1D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX1D(fgINT16);
}
int check_neighbor_box1d_fgINT32(FLGR_NhbBox1D *extr1, FLGR_NhbBox1D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX1D(fgINT32);
}
int check_neighbor_box1d_fgFLOAT32(FLGR_NhbBox1D *extr1, FLGR_NhbBox1D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX1D(fgFLOAT32);
}
int check_neighbor_box1d_fgFLOAT64(FLGR_NhbBox1D *extr1, FLGR_NhbBox1D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX1D(fgFLOAT64);
}

int check_neighbor_box1d(FLGR_NhbBox1D *extr1, FLGR_NhbBox1D *extr2) {
  switch(extr1->type) {
  case FLGR_BIT:      return check_neighbor_box1d_fgBIT(extr1,extr2);break;
  case FLGR_UINT8:    return check_neighbor_box1d_fgUINT8(extr1,extr2);break;
  case FLGR_UINT16:   return check_neighbor_box1d_fgUINT16(extr1,extr2);break;
  case FLGR_UINT32:   return check_neighbor_box1d_fgUINT32(extr1,extr2);break;
  case FLGR_INT8:     return check_neighbor_box1d_fgINT8(extr1,extr2);break;
  case FLGR_INT16:    return check_neighbor_box1d_fgINT16(extr1,extr2);break;
  case FLGR_INT32:    return check_neighbor_box1d_fgINT32(extr1,extr2);break;
  case FLGR_FLOAT32:  return check_neighbor_box1d_fgFLOAT32(extr1,extr2);break;
  case FLGR_FLOAT64:  return check_neighbor_box1d_fgFLOAT64(extr1,extr2);break;
  default:
    fprintf(stderr,"%s:type error\n",__FUNCTION__);  
    return -1;
  }
}



int _check_and_display_box1d(FLGR_NhbBox1D *extrref, FLGR_NhbBox1D *extr, FLGR_Ret ret,const char *calling_fct) {
  printf("%s",calling_fct);					
  if(ret!=FLGR_RET_NOT_IMPLEMENTED) {			
    if(check_neighbor_box1d(extrref, extr)==-1) {	
      printf(": failed!\n");				
      printf("Neighbor Box1d Reference:\n");		
      print_neighbor_box1d(extrref);		
      printf("Neighbor Box1d Obtained:\n");		
      print_neighbor_box1d(extr);			
      return -1;					
      
    }else {						
      printf(": ok\n");					
      
    }							
  }else printf(": NOT IMPLEMENTED\n");

  return 0;
}






/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// NHB BOX2D CHECK
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////




#define FLGR_MACRO_PRINT_NEIGHBOR_BOX2D(dtype,motif)			\
  dtype *list_data_val;							\
  dtype *list_nhb_val;							\
  int *list_coord_x;							\
  int *list_coord_y;							\
  int *size = (int *) extr->size;					\
  int i,k;								\
									\
  printf("--------------------------------------\n");			\
  printf("Center coord  x : %d\n",extr->center_coord_x);		\
  printf("Center coord  y : %d\n",extr->center_coord_y);		\
  printf("Center Data val : ");						\
  display_vector(extr->center_data_val);				\
  printf("\nCenter Nhb val : ");					\
  display_vector(extr->center_nhb_val);					\
									\
  for(k=0 ; k<extr->spp ; k++) {					\
    list_data_val = (dtype *) extr->list_data_val[k];			\
    list_nhb_val = (dtype *) extr->list_nhb_val[k];			\
    list_coord_x =(int*) extr->list_coord_x[k];				\
    list_coord_y =(int*) extr->list_coord_x[k];				\
    printf("\n\nChannel %d\n",k);					\
									\
    printf("\nCoord Y: ");						\
    for(i=0 ; i<size[k] ; i++) printf("%3d ",list_coord_y[i]);		\
									\
    printf("\nCoord X: ");						\
    for(i=0 ; i<size[k] ; i++) printf("%3d ",list_coord_x[i]);		\
									\
    printf("\nData  : ");						\
    for(i=0 ; i<size[k] ; i++) printf(motif " ",list_data_val[i]);	\
									\
    printf("\nNhb   : ");						\
    for(i=0 ; i<size[k] ; i++) printf(motif " ",list_nhb_val[i]);	\
									\
    printf("\n--------------------------------------\n");		\
  }									\
       

void print_neighbor_box2d_fgBIT(FLGR_NhbBox2D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX2D(fgBIT,"%3Ld");
}
void print_neighbor_box2d_fgUINT8(FLGR_NhbBox2D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX2D(fgUINT8,"%3d");
}
void print_neighbor_box2d_fgUINT16(FLGR_NhbBox2D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX2D(fgUINT16,"%3d");
}
void print_neighbor_box2d_fgUINT32(FLGR_NhbBox2D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX2D(fgUINT32,"%3d");
}
void print_neighbor_box2d_fgINT8(FLGR_NhbBox2D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX2D(fgINT8,"%3d");
}
void print_neighbor_box2d_fgINT16(FLGR_NhbBox2D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX2D(fgINT16,"%3d");
}
void print_neighbor_box2d_fgINT32(FLGR_NhbBox2D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX2D(fgINT32,"%3d");
}
void print_neighbor_box2d_fgFLOAT32(FLGR_NhbBox2D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX2D(fgFLOAT32,"%.2f");
}
void print_neighbor_box2d_fgFLOAT64(FLGR_NhbBox2D *extr) {
  FLGR_MACRO_PRINT_NEIGHBOR_BOX2D(fgFLOAT64,"%.2f");
}

void print_neighbor_box2d(FLGR_NhbBox2D *extr) {
  switch(extr->type) {
  case FLGR_BIT:      print_neighbor_box2d_fgBIT(extr);break;
  case FLGR_UINT8:    print_neighbor_box2d_fgUINT8(extr);break;
  case FLGR_UINT16:   print_neighbor_box2d_fgUINT16(extr);break;
  case FLGR_UINT32:   print_neighbor_box2d_fgUINT32(extr);break;
  case FLGR_INT8:     print_neighbor_box2d_fgINT8(extr);break;
  case FLGR_INT16:    print_neighbor_box2d_fgINT16(extr);break;
  case FLGR_INT32:    print_neighbor_box2d_fgINT32(extr);break;
  case FLGR_FLOAT32:  print_neighbor_box2d_fgFLOAT32(extr);break;
  case FLGR_FLOAT64:  print_neighbor_box2d_fgFLOAT64(extr);break;
  default:
    fprintf(stderr,"%s:type error\n",__FUNCTION__);    
  }
}





#define FLGR_MACRO_CHECK_NEIGHBOR_BOX2D(dtype)				\
  dtype *list_data_val1;						\
  dtype *list_nhb_val1;							\
  int *list_coord_x1;							\
  int *list_coord_y1;							\
  int *size1 = (int*) extr1->size;					\
  dtype *list_data_val2;						\
  dtype *list_nhb_val2;							\
  int *list_coord_x2;							\
  int *list_coord_y2;							\
  int *size2 = (int*) extr2->size;					\
  int i,k;								\
									\
  if(extr1->spp != extr2->spp) {					\
    fprintf(stderr,"Sample per pixel error\n");				\
    return -1;								\
  }									\
									\
  if(extr1->nhb_size_x != extr2->nhb_size_x) {				\
    fprintf(stderr,"nhb size x error\n");				\
    return -1;								\
  }									\
									\
  if(extr1->nhb_size_y != extr2->nhb_size_y) {				\
    fprintf(stderr,"nhb size y error\n");				\
    return -1;								\
  }									\
									\
  for(k=0 ; k<extr1->spp ; k++) {					\
    if(size1[k] != size2[k]) {						\
      fprintf(stderr,"neighbor box2d size error\n");			\
      return -1;							\
    }									\
  }									\
									\
  if(extr1->center_coord_x != extr2->center_coord_x) {			\
    fprintf(stderr,"center coord error\n");				\
    return -1;								\
  }									\
									\
  if(extr1->center_coord_y != extr2->center_coord_y) {			\
    fprintf(stderr,"center coord error\n");				\
    return -1;								\
  }									\
									\
  									\
  if(flgr_vector_equal(extr1->center_data_val, extr2->center_data_val)	\
     != FLGR_TRUE) {							\
    fprintf(stderr,"center data error\n");				\
    return -1;								\
  }									\
									\
  if(flgr_vector_equal(extr1->center_nhb_val, extr2->center_nhb_val)	\
     != FLGR_TRUE) {							\
    fprintf(stderr,"center nhb error\n");				\
    return -1;								\
  }									\
									\
  for(k=0 ; k<extr1->spp ; k++) {					\
									\
    list_data_val1 = (dtype *) extr1->list_data_val[k];			\
    list_nhb_val1 = (dtype *) extr1->list_nhb_val[k];			\
    list_coord_x1 = (int*) extr1->list_coord_x[k];			\
    list_coord_y1 = (int*) extr1->list_coord_y[k];			\
    list_data_val2 = (dtype *) extr2->list_data_val[k];			\
    list_nhb_val2 = (dtype *) extr2->list_nhb_val[k];			\
    list_coord_x2 =(int*) extr2->list_coord_x[k];			\
    list_coord_y2 =(int*) extr2->list_coord_y[k];			\
									\
    for(i=0 ; i<size1[k] ; i++) {					\
      if(list_coord_x1[i] != list_coord_x2[i]) {			\
	fprintf(stderr,"extracted list coord error\n");			\
	return -1;							\
      }									\
      if(list_coord_y1[i] != list_coord_y2[i]) {			\
	fprintf(stderr,"extracted list coord error\n");			\
	return -1;							\
      }									\
      if(list_nhb_val1[i] != list_nhb_val2[i]) {			\
	fprintf(stderr,"extracted list nhb error\n");			\
	return -1;							\
      }									\
      if(list_data_val1[i] != list_data_val2[i]) {			\
	fprintf(stderr,"extracted list data error\n");			\
	return -1;							\
      }									\
    }									\
  }									\
									\
  return 0

int check_neighbor_box2d_fgBIT(FLGR_NhbBox2D *extr1, FLGR_NhbBox2D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX2D(fgBIT);
}
int check_neighbor_box2d_fgUINT8(FLGR_NhbBox2D *extr1, FLGR_NhbBox2D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX2D(fgUINT8);
}
int check_neighbor_box2d_fgUINT16(FLGR_NhbBox2D *extr1, FLGR_NhbBox2D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX2D(fgUINT16);
}
int check_neighbor_box2d_fgUINT32(FLGR_NhbBox2D *extr1, FLGR_NhbBox2D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX2D(fgUINT32);
}
int check_neighbor_box2d_fgINT8(FLGR_NhbBox2D *extr1, FLGR_NhbBox2D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX2D(fgINT8);
}
int check_neighbor_box2d_fgINT16(FLGR_NhbBox2D *extr1, FLGR_NhbBox2D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX2D(fgINT16);
}
int check_neighbor_box2d_fgINT32(FLGR_NhbBox2D *extr1, FLGR_NhbBox2D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX2D(fgINT32);
}
int check_neighbor_box2d_fgFLOAT32(FLGR_NhbBox2D *extr1, FLGR_NhbBox2D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX2D(fgFLOAT32);
}
int check_neighbor_box2d_fgFLOAT64(FLGR_NhbBox2D *extr1, FLGR_NhbBox2D *extr2) {
  FLGR_MACRO_CHECK_NEIGHBOR_BOX2D(fgFLOAT64);
}

int check_neighbor_box2d(FLGR_NhbBox2D *extr1, FLGR_NhbBox2D *extr2) {
  switch(extr1->type) {
  case FLGR_BIT:      return check_neighbor_box2d_fgBIT(extr1,extr2);break;
  case FLGR_UINT8:    return check_neighbor_box2d_fgUINT8(extr1,extr2);break;
  case FLGR_UINT16:   return check_neighbor_box2d_fgUINT16(extr1,extr2);break;
  case FLGR_UINT32:   return check_neighbor_box2d_fgUINT32(extr1,extr2);break;
  case FLGR_INT8:     return check_neighbor_box2d_fgINT8(extr1,extr2);break;
  case FLGR_INT16:    return check_neighbor_box2d_fgINT16(extr1,extr2);break;
  case FLGR_INT32:    return check_neighbor_box2d_fgINT32(extr1,extr2);break;
  case FLGR_FLOAT32:  return check_neighbor_box2d_fgFLOAT32(extr1,extr2);break;
  case FLGR_FLOAT64:  return check_neighbor_box2d_fgFLOAT64(extr1,extr2);break;
  default:
    fprintf(stderr,"%s:type error\n",__FUNCTION__);  
    return -1;
  }
}



int _check_and_display_box2d(FLGR_NhbBox2D *extrref, FLGR_NhbBox2D *extr, FLGR_Ret ret,const char *calling_fct) {
  printf("%s",calling_fct);					
  if(ret!=FLGR_RET_NOT_IMPLEMENTED) {			
    if(check_neighbor_box2d(extrref, extr)==-1) {	
      printf(": failed!\n");				
      printf("Neighbor Box2d Reference:\n");		
      print_neighbor_box2d(extrref);		
      printf("Neighbor Box2d Obtained:\n");		
      print_neighbor_box2d(extr);			
      return -1;					
      
    }else {						
      printf(": ok\n");					
      
    }							
  }else printf(": NOT IMPLEMENTED\n");

  return 0;
}




